package sh.grapendaal.tsuushin.module.uno.engine.domain;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import sh.grapendaal.tsuushin.module.uno.engine.domain.Card.Suit;
import sh.grapendaal.tsuushin.module.uno.engine.domain.achievement.Achievement;

public class Player {

	private String nickname;
	private List<Card> cards = new ArrayList<Card>();
	private List<Card> newCards = new ArrayList<Card>();
	private Card drawnCard = null;
	private boolean isTurn = false;
	private Statistics statistics;
	private Set<Class<? extends Achievement>> unlockedAchievements;

	public Player(String nickname) {
		this(nickname, new Statistics(), new HashSet<Class<? extends Achievement>>());
	}
	
	public Player(String nickname, Statistics statistics, Set<Class<? extends Achievement>> unlockedAchievements) {
		this.nickname = nickname;
		this.statistics = statistics;
		this.unlockedAchievements = unlockedAchievements;
	}

	public String getNickname() {
		return nickname;
	}

	public Statistics getStatistics() {
		return statistics;
	}
	
	public Set<Class<? extends Achievement>> getUnlockedAchievements() {
		return unlockedAchievements;
	}

	public void unlockAchievement(Achievement achievement) {
		this.unlockedAchievements.add(achievement.getClass());
	}

	public void addCard(Card card, boolean isDrawn) {
		this.cards.add(card);
		Collections.sort(this.cards);
		
		if (!this.isTurn) {
			this.newCards.add(card);
			Collections.sort(this.newCards);
		}
		
		this.drawnCard = isDrawn ? card : null;
	}

	public boolean hasCard(Card card) {
		return this.cards.contains(card);
	}
	
	public void removeCard(Card card) {
		this.cards.remove(card);
	}
	
	public List<Card> getCards() {
		return this.cards;
	}
	
	public List<Card> getNewCards() {
		return this.newCards;
	}

	public Card playCard(Card playedCard) {
		Iterator<Card> itCards = this.cards.iterator();
		while (itCards.hasNext()) {
			Card card = itCards.next();
			if (card.equals(playedCard)) {
				itCards.remove();
				if (card.getSuit() == Suit.WILDCARD) {
					card.setNextSuit(playedCard.getNextSuit());
				}
				return card;
			}
		}
		return null;
	}
	
	public Card getDrawnCard() {
		return this.drawnCard;
	}
	
	public boolean hasDrawnCard() {
		return this.drawnCard != null;
	}
	
	public boolean isTurn() {
		return this.isTurn;
	}
	
	public void startTurn() {
		this.isTurn = true;
	}

	public void endTurn() {
		this.isTurn = false;
		this.drawnCard = null;
	}

	@Override
	public String toString() {
		return "Player [nickname=" + nickname + "]";
	}

	@Override
	public int hashCode() {
		return new HashCodeBuilder().append(this.nickname).toHashCode();
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj instanceof Player) {
			Player other = (Player) obj;
			return new EqualsBuilder().append(this.nickname, other.nickname).isEquals();
		}
		return false;
	}
}
